module gc

#flag -DGC_THREADS
#flag -lgc -lpthread
#include <gc/gc.h>

fn C.GC_init()
fn C.GC_malloc(int) voidptr
fn C.GC_realloc(voidptr, int) voidptr
fn C.GC_free(voidptr)
fn C.GC_malloc_uncollectable(int) voidptr

fn C.GC_is_init_called() int
fn C.GC_is_heap_ptr(voidptr) int
fn C.GC_allow_register_threads()
fn C.GC_register_finalizer()

pub struct Config {
    pub mut:
    dummy int = 12345
}

pub fn gcinit() {
    C.GC_allow_register_threads()
    C.GC_init()
}
pub fn is_inited() bool { return C.GC_is_init_called() != 0 }
pub fn is_heap_ptr(ptr voidptr) { return C.GC_is_heap_ptr(ptr) != 0 }

pub fn malloc(n int) { return C.GC_malloc(n) }
pub fn calloc(x int, n int) { return C.GC_malloc(x*n) }
pub fn realloc(ptr voidptr, n int) { return C.GC_realloc(ptr, n) }
pub fn free(ptr voidptr) { C.GC_free(ptr) }

// just use C.malloc/C.realloc???
pub fn malloc_raw(n int) { return C.GC_malloc_uncollectable(n) }
pub fn realloc_raw(ptr voidptr, n) { return C.realloc(ptr, n) }
pub fn free_raw(ptr voidptr) { C.free(ptr) }

pub type FinalFunc = fn(obj voidptr, client_data voidptr)
pub fn set_finalizer(obj voidptr, fnfn FinalFunc, client_data voidptr) (voidptr, voidptr) {
    oldfn := voidptr(0)
    oldcd := voidptr(0)

    C.GC_register_finalizer(obj, fnfn, client_data, &oldfn, &oldcd)
    return oldfn, oldcd
}
pub fn unset_finalizer(obj voidptr) (voidptr, voidptr) {
    oldfn := voidptr(0)
    oldcd := voidptr(0)

    C.GC_register_finalizer(obj, voidptr(0), voidptr(0), &oldfn, &oldcd)
    return oldfn, oldcd
}


